// Include Files
#include "Rendering\GLExt.h"
//#include "GLee\GLee.h"

#include "Systems\Window.h"
#include <process.h>

// ISingleton<CWindow> Static Initialization
CWindow * ISingleton<CWindow>::m_pInstance = CE_NULL;

// CWindow Implementation
void CWindow::Create()
{
	m_hApplication = GetModuleHandle(NULL);
	m_strTitle     = L"Galleons";
	m_uiWidth      = 800;
	m_uiHeight     = 600;
	m_bFullscreen  = CE_FALSE;
	StartProcess(15);
}

void CWindow::Destroy()
{
	StopProcess();
}

void CWindow::Show()
{
	// TODO: this must happen in the window thread
}

void CWindow::Hide()
{
}

CWindow::CWindow() : 
	m_hApplication( CE_NULL ), 
	m_hWindow( CE_NULL ), 
	m_strTitle(), 
	m_uiWidth(800), 
	m_uiHeight(600), 
	m_bFullscreen( CE_FALSE )
{ }

CWindow::~CWindow()
{ }

void CWindow::ProcessBegin()
{
	// register the window class
	WNDCLASSEX wcex;
	wcex.cbSize        = sizeof(WNDCLASSEX);
	wcex.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
	wcex.lpfnWndProc   = WindowProc;
	wcex.cbClsExtra    = 0;
	wcex.cbWndExtra    = 0;
	wcex.hInstance     = m_hApplication;
	wcex.hIcon         = LoadIcon( NULL, IDI_APPLICATION );
	wcex.hCursor       = LoadCursor( NULL, IDC_ARROW );
	wcex.hbrBackground = NULL;
	wcex.lpszMenuName  = NULL;
	wcex.lpszClassName = m_strTitle;
	wcex.hIconSm       = NULL;
	if( !RegisterClassEx(&wcex) )
	{
		assert(false);
	}

	// find the window style
	DWORD dwStyleFlags   = m_bFullscreen ? WS_POPUP : WS_OVERLAPPEDWINDOW;
	DWORD dwExStyleFlags = WS_EX_APPWINDOW;

	// get the window rect corrected for the border style
	RECT rWindow;
	rWindow.left   = 0;
	rWindow.top    = 0;
	rWindow.right  = m_uiWidth;
	rWindow.bottom = m_uiHeight;
	AdjustWindowRectEx( &rWindow, dwStyleFlags, FALSE, dwExStyleFlags );

	// get the size and position of the window
	int_t iWindowWidth  = rWindow.right - rWindow.left;
	int_t iWindowHeight = rWindow.bottom - rWindow.top;
	int_t iWindowX      = m_bFullscreen ? 0 : 
		GetSystemMetrics(SM_CXSCREEN) / 2 - iWindowWidth / 2;
	int_t iWindowY      = m_bFullscreen ? 0 : 
		GetSystemMetrics(SM_CYSCREEN) / 2 - iWindowHeight / 2;

	// create the window
	char_t const * szTitle = (char_t const *)m_strTitle;
	m_hWindow = CreateWindowEx( 
		dwExStyleFlags, // dwExStyle
		szTitle,        // lpClassName
		szTitle,        // lpWindowName
		dwStyleFlags,   // dwStyle
		iWindowX,       // x
		iWindowY,       // y
		iWindowWidth,   // nWidth
		iWindowHeight,  // nHeight
		NULL,           // hWndParent
		NULL,           // hMenu
		m_hApplication, // hInstance
		NULL );         // lpParam
	assert(m_hWindow);

	// HACK HACK HACK HACK!!!! window gets created twice, only show it the second time
	static int i = 0;
	i++;
	if( i == 2 )
	{
		ShowWindow(m_hWindow, SW_SHOWNORMAL);
	}
}

void CWindow::ProcessEnd()
{
	if( m_hWindow && !DestroyWindow(m_hWindow) )
	{
		assert(false);
	}
	m_hWindow = CE_NULL;

	if( !UnregisterClass( m_strTitle, m_hApplication ) )
	{
		assert(false);
	}
	m_hApplication = CE_NULL;
}

void CWindow::ProcessTick( float_t _fTime )
{
	(void)_fTime;

	// handle windows messages
	MSG msg;
	while( PeekMessage( &msg, m_hWindow, 0, 0, PM_REMOVE ) )
	{
		DispatchMessage(&msg);
	}
}

LRESULT CALLBACK CWindow::WindowProc( 
	HWND _hWindow, UINT _uiMessage, WPARAM _WParam, LPARAM _LParam )
{
	CSingleton<CWindow> pWindow;

	switch(_uiMessage)
	{

	case WM_ERASEBKGND:
	case WM_PAINT:
		// don't waste any time
		ValidateRect( _hWindow, NULL );
		return 0;

	//case WM_ACTIVATE:
	//	if( LOWORD(_WParam) == WA_ACTIVE )
	//	{
	//	}
	//	else
	//	{
	//	}
	//	return 0;

	case WM_CLOSE:
#pragma warning(disable:981)
		pWindow->Close.Raise(new CEventArg());
#pragma warning(default:981)
		return 0;

	//case WM_SIZE:
	//	//rWindow->ReSizeGLScene( LOWORD(_lparam), HIWORD(_lparam) );
	//	return 0;
	}

	return DefWindowProc( _hWindow, _uiMessage, _WParam, _LParam );
}
